[java] BufferedReader/BufferedWriter 클래스

1. BufferedReader와 BufferedWriter의 특징

  • 입출력 데이터가 바로 전달되지 않고 *Buffer(버퍼)를 거쳐 전달된다.
  • 키보드 입력이 있을 때마다 한 문자씩 버퍼로 전송되고, 버퍼가 가득 차거나 개행문자가 나타나면 버퍼의 내용을 한번에 프로그램에 전달한다.
  • java.io 패키지에 존재한다.
  • 속도가 빠르다.
    (흙을 파서 언덕에 버릴 때, 한번 삽질할 때마다 가서 버리는 것보다 수레에 가득 채워서 한번에 나르는 것이 더 효과적인 것과 같은 이치)


* Buffer
데이터를 한 곳에서 다른 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 임시 메모리 영역




2. BufferedReader 클래스

- Scanner 클래스와의 차이

  1. Scanner
    • 장점
      • 공백문자(' ', '\t', '\n')를 경계로 하여 입력 값을 인식한다.
        그렇기 때문에 따로 가공할 필요가 없어 편리하다.
      • 또한, 다양한 변수형에 맞는 메서드들이 있어 원하는 타입의 값을 바로 입력받을 수 있다.
    • 단점
      • 버퍼 사이즈가 1024 char이기 때문에, 많은 입력을 필요로 할 경우에는 성능상 좋지 못한 결과를 불러온다.
      • 동기화가 되지 않기 때문에 멀티스레드에 안전하지 않다.
  2. BufferedReader
    • 장점
      • Scanner보다 속도가 빠르다.
      • 버퍼 사이즈가 8192 char(16,384byte) 이기 때문에, 입력이 많을 때 유리하다.
      • 동기화가 되기 때문에 멀티스레드에 안전하다.
    • 단점
      • 개행문자('\n')만 경계로 인식한다.
        그래서 입력받은 데이터가 String 으로 고정되어 있어, 원하는 타입으로
        가공하는 작업이 추가로 필요하다.
      • 예외처리를 반드시 필요로 한다.
        readLine()시 마다 try/catch문으로 감싸주거나, throws IOException 을 통한 예외처리를 해도 된다.(대부분의 경우에 후자를 사용)


Scanner에 대해 더 자세히 알고싶다면 여기를 눌러보자




- BufferedReader 사용법

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  • BufferedReader는 객체를 생성할 때, * InputStreamReader 객체생성자의 인자로 전달한다.
  • BufferedReader를 통해 읽어온 데이터는 개행문자 단위(Line 단위)로 나누어진다.
  • 만약 이를 공백 단위로 데이터를 가공하고자 하면 따로 작업을 해주어야 한다.
    이때 사용하는 것이 * StringTokenizer 클래스나 * String.split() 메서드다.

* InputStreamReader
InputStreamReader 클래스는 바이트 단위 데이터를 문자 단위 데이터로 처리할 수 있도록 변환해준다.
그래서 inputStream으로는 읽지 못하는 3byte 의 한글을 읽을 수 있고, char 배열로 데이터를 받을 수 있다.

그러나 우리가 문자열을 입력하고 싶다면 매번 배열을 선언해야 한다는 단점이 있다.
이 때, 함께 쓰는 것이 BufferedReader이다.
BufferedReader를 사용해서 Buffer(버퍼)에 입력받은 문자를 쌓아둔 뒤 한번에 문자열처럼 보낸다.
* StringTokenizer
StringTokenizer 클래스는 우리가 지정한 구분자로 문자열을 쪼개주는 클래스입니다.
그렇게 쪼개어진 문자열을 우리는 토큰(token)이라고 부릅니다.
* String.split()
String 클래스의 split() 메서드는 구분자를 기준으로 문자열을 쪼개어 배열에 담아 저장하는 함수이다.
split(" ")처럼 인수에 공백과 같은 구분자를 넣어주면 된다.




아래의 예제를 보자

//java.io 패키지에 있는 (BufferedReader, InputStreamReader, IOException) import 필수
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
//java.util 패키지에 있는 StringTokenizer import 필수
import java.util.StringTokenizer;

public class Main{
					   //예외처리가 반드시 필요!!
    public static void main(String[] args) throws IOException{

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        //readLine() 메서드를 사용해서 String형 변수에 입력값 저장
        String str = br.readLine();

	//1. StringTokenizer
	StringTokenizer st = new StringTokenizer(str);
	//공백문자가 나오기 전까지의 입력값을 A에 저장
	int A = Integer.parseInt(st.nextToken());
	//두번째 공백문자가 나오기 전까지의 입력값을 B에 저장
	int B = Integer.parseInt(st.nextToken());

	//2. String.split()
	//문자열을 공백단위로 끊어 배열에 저장
	String arr[] = str.split(" ");
    }
}

아래의 코드를 자세히 알아보자.

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

1.inbyte 타입으로 입력값을 읽어들인다.
2.InputStreamReader가 1번의 값을 char 타입으로 변환한다.
3.BufferedReader가 2번의 값을 버퍼에 저장했다가 한번에 문자열로 반환한다.

StringTokenizer의 nextToken() 함수를 쓰면 readLine()을 통해 입력 받은 값을 공백 단위로 구분하여 순서대로 호출할 수 있다.

split()을 사용하면, 입력받은 값을 공백단위로 끊어 배열에 데이터를 저장한다.




- 대표 메서드

메서드 리턴타입 설명
read() int 문자 하나를 읽어 int형으로 리턴
ex) ‘3’을 읽고 정수형인 (int)’3’ = 51로 반환
readLine() String 한 줄의 문자열을 읽음
skip(n) long n개의 문자를 스킵하고 넘어감
close() void 입력 스트림을 닫고, 사용하던 자원을 해제





3. BufferedWriter 클래스

일반적으로 출력을 할 때는 System.out.println("");을 사용하는데, 적은 양의 출력에서는 편리하다.
하지만 BufferedWriter는 버퍼를 사용하기 때문에 속도와 성능면에서 더 뛰어나고, 많은 양의 데이터를 처리할 때 이득이다.

그러나 System.out.println();처럼 출력과 개행을 동시에 해주지 않기 때문에, 개행이 필요한 경우에는 반드시 bw.write("\n") 혹은 newLine() 메서드를 사용해야 한다.

또한, BufferedWriter 의 경우 버퍼를 잡아 놓았기 때문에 반드시 flush() / close() 를 반드시 호출해 주어 버퍼를 클린하게 해줘야 한다.




- BufferedWriter 사용법

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class Main {
                                          	//예외처리 필수
	public static void main(String[] args) throws IOException {
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));  //BufferedWriter 객체 선언
		String s = "abcdefg";  
		bw.write(s+"\n");  
		//bw.newLine();
		bw.flush();  //버퍼에 남아있는 데이터를 모두 출력
		bw.close();  //스트림을 닫음
	}
}
주의!!

.write()만 사용한다고 콘솔에 출력되는 것이 아니라 flush()를 사용해 버퍼를 비우는 동시에 출력해야 한다.
BufferedWriter 역시 BufferedReader와 마찬가지로 IOException 예외 처리를 반드시 해 주어야 한다.




- 대표 메서드

메서드 리턴타입 설명
write(int c) void int형을 문자 데이터로 바꿔
출력문자 스트림으로 출력
write(char[] cbuf,int offset,int length) void 문자배열에서 offset위치부터
length만큼 출력스트림으로 출력
write(String s,int offset,int length) void 문자열에서 offset위치부터
length만큼 출력스트림으로 출력
newLine() void 개행
flush() void 남아있는 데이터를 모두 출력해서
스트림을 비움
close() void 입력 스트림을 닫고,
사용하던 자원을 해제




관련 페이지


참고링크 |
크크님 blog


Categories:

Updated:

Leave a comment